---
title: "Python Cgi笔记"
categories:
- python
tags:
---

<div id="content">
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#org8f7b105">Python CGI简单示例</a></li>
<li><a href="#org3ded2ac">简单的HTTP POST</a></li>
<li><a href="#orgcf86c6c">POST Body</a></li>
<li><a href="#orgd98dacd">POST File</a></li>
<li><a href="#orgff47b02">Return Status Code 返回http状态码</a></li>
</ul>
</div>
</div>
<div class="outline-2" id="outline-container-org8f7b105">
<h2 id="org8f7b105">Python CGI简单示例</h2>
<div class="outline-text-2" id="text-org8f7b105">
<div class="org-src-container">
<pre class="src src-python" id="orga37cdfe"><span style="font-weight: bold; font-style: italic;">#</span><span style="font-weight: bold; font-style: italic;">! /usr/bin/python3              # 执行此脚本的程序，确保路径正确，不要包含这个注释</span>
<span style="font-weight: bold;">import</span> cgi
<span style="font-weight: bold;">import</span> cgitb                     <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">用于显示错误</span>
cgitb.enable()

<span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Content-Type: text/palin"</span>)<span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">Response Header</span>
<span style="font-weight: bold;">print</span>()                          <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">Response header end，使用一个换行符表示响应头部的结束，HTTP协议中的定义</span>
<span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"CGI worked"</span>)
<span style="font-weight: bold;">print</span>()
</pre>
</div>
<p>
使用支持CGI的Web服务器，以Apache为例，将脚本放置在目录。
假如Apache服务器以apache用户运行，需要赋予脚本apache用户的执行权限。
</p>
<p>
故障排除方法：
</p>
<ul class="org-ul">
<li>检查脚本能否执行： {% raw %} sudo -u apache /var/www/cgi-bin/hello.py {% endraw %}</li>
<li>404: web服务器是否开启了cgi功能；cgi配置的访问路径，例如ubuntu1804上的apache2服务器，默认配置的话，我通过src_shell[curl localhots/cgi-bin/hello.py]访问。</li>
<li>如果服务器返回500，通过web服务器的日志查看错误，根据web服务器的配置找到error_log的位置，apache服务器一般位于/var/log/apache</li>
<li>End of script output before headers. 出现这种问题，一般是脚本抛出了异常，异常信息出现在print response header之前。</li>
</ul>
</div>
</div>
<div class="outline-2" id="outline-container-org3ded2ac">
<h2 id="org3ded2ac">简单的HTTP POST</h2>
<div class="outline-text-2" id="text-org3ded2ac">
<p>
以下是我自用的一个使用了POST的脚本。
</p>
<div class="org-src-container">
<pre class="src src-python"><span style="font-weight: bold;">import</span> cgi
<span style="font-weight: bold;">import</span> cgitb
cgitb.enable()
<span style="font-weight: bold;">import</span> os, sys

<span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Content-Type: text/plain"</span>)
<span style="font-weight: bold;">print</span>()

<span style="font-weight: bold; font-style: italic;">form</span> = cgi.FieldStorage() <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">这个form中存储了POST表单</span>

<span style="font-weight: bold; font-style: italic;">vm_ip</span> = form.getvalue(<span style="font-style: italic;">"ip"</span>) <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">获取Form表单中名字为ip的字段的值</span>
<span style="font-weight: bold;">if</span> vm_ip <span style="font-weight: bold;">is</span> <span style="font-weight: bold; text-decoration: underline;">None</span> <span style="font-weight: bold;">or</span> <span style="font-weight: bold;">len</span>(vm_ip) == 0:
    <span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Empty form field: ip"</span>)
    <span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Result: False"</span>)
    <span style="font-weight: bold; text-decoration: underline;">exit</span>()

<span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">执行业务逻辑了       </span>
<span style="font-weight: bold; font-style: italic;">data_dir</span> = os.path.join(sys.path[0], <span style="font-style: italic;">'data'</span>)
<span style="font-weight: bold;">if</span> <span style="font-weight: bold;">not</span> os.path.isdir(data_dir):
    <span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Data dir not exists: %s"</span> % data_dir)
    <span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Result: False"</span>)
    <span style="font-weight: bold; text-decoration: underline;">exit</span>()
<span style="font-weight: bold; font-style: italic;">fd</span> = <span style="font-weight: bold;">open</span>(os.path.join(data_dir, <span style="font-style: italic;">"cm-hyper-v-ip"</span>), <span style="font-style: italic;">'w'</span>)
fd.write(vm_ip)
fd.close()

<span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Result: True"</span>)
</pre>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-orgcf86c6c">
<h2 id="orgcf86c6c">POST Body</h2>
<div class="outline-text-2" id="text-orgcf86c6c">
<div class="org-src-container">
<pre class="src src-python"><span style="font-weight: bold; font-style: italic;">#</span><span style="font-weight: bold; font-style: italic;">! /usr/bin/python3</span>

<span style="font-weight: bold;">import</span> cgi, os, sys
<span style="font-weight: bold;">import</span> cgitb                     <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">用于显示错误</span>
cgitb.enable()

<span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Content-Type: text/plain"</span>)<span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">Response Header</span>
<span style="font-weight: bold;">print</span>()                          <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">Response header end，使用一个换行符表示响应头部的结束，HTTP协议中的定义</span>

<span style="font-weight: bold;">if</span> <span style="font-style: italic;">"CONTENT_TYPE"</span> <span style="font-weight: bold;">in</span> os.environ:
    <span style="font-weight: bold; font-style: italic;">cont_len</span> = <span style="font-weight: bold;">int</span>(os.environ[<span style="font-style: italic;">"CONTENT_LENGTH"</span>])
    <span style="font-weight: bold; font-style: italic;">body</span> = sys.stdin.read(cont_len)
    <span style="font-weight: bold;">print</span>(body)
    <span style="font-weight: bold;">print</span>()
<span style="font-weight: bold;">else</span>:
    <span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Body is empty"</span>)
</pre>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-orgd98dacd">
<h2 id="orgd98dacd">POST File</h2>
<div class="outline-text-2" id="text-orgd98dacd">
<div class="org-src-container">
<pre class="src src-python"><span style="font-weight: bold; font-style: italic;">#</span><span style="font-weight: bold; font-style: italic;">! /usr/bin/python3</span>
<span style="font-weight: bold;">import</span> cgi, os, sys
<span style="font-weight: bold;">import</span> cgitb; cgitb.enable()
<span style="font-weight: bold; font-style: italic;">DATA_DIR</span>=<span style="font-style: italic;">"/data/www-data/file-upload"</span>
<span style="font-weight: bold; font-style: italic;">form</span> = cgi.FieldStorage()
<span style="font-weight: bold; font-style: italic;">fileitem</span> = form[<span style="font-style: italic;">'file'</span>] <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">form input name</span>
<span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"Content-Type: text/plain"</span>)
<span style="font-weight: bold;">print</span>()
<span style="font-weight: bold;">if</span> fileitem.filename:
    <span style="font-weight: bold; font-style: italic;">local_path</span> = os.path.join(DATA_DIR, fileitem.filename)
    <span style="font-weight: bold; font-style: italic;">fd</span> = <span style="font-weight: bold;">open</span>(local_path, <span style="font-style: italic;">'wb'</span>) <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">open for write in binary mode</span>
    <span style="font-weight: bold; font-style: italic;">data</span> = fileitem.<span style="font-weight: bold;">file</span>.read() <span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">read file stream</span>
    fd.write(data)
    fd.close()
    <span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"File writeen to %s"</span> % local_path)
<span style="font-weight: bold;">else</span>:
    <span style="font-weight: bold;">print</span>(<span style="font-style: italic;">"No file found"</span>)
</pre>
</div>
<div class="org-src-container">
<pre class="src src-html">&lt;<span style="font-weight: bold;">html</span>&gt;
        &lt;<span style="font-weight: bold;">head</span>&gt;
                &lt;<span style="font-weight: bold;">title</span>&gt;<span style="font-weight: bold; text-decoration: underline;">File Upload</span>&lt;/<span style="font-weight: bold;">title</span>&gt;
        &lt;/<span style="font-weight: bold;">head</span>&gt;
        &lt;<span style="font-weight: bold;">body</span>&gt;
                &lt;<span style="font-weight: bold;">form</span> <span style="font-weight: bold; font-style: italic;">action</span>=<span style="font-style: italic;">"/cgi-bin/file-upload.py"</span> <span style="font-weight: bold; font-style: italic;">method</span>=<span style="font-style: italic;">"POST"</span> <span style="font-weight: bold; font-style: italic;">enctype</span>=<span style="font-style: italic;">"multipart/form-data"</span>&gt;
                        &lt;<span style="font-weight: bold;">input</span> <span style="font-weight: bold; font-style: italic;">type</span>=<span style="font-style: italic;">"file"</span> <span style="font-weight: bold; font-style: italic;">name</span>=<span style="font-style: italic;">"file"</span> /&gt;
                        &lt;<span style="font-weight: bold;">input</span> <span style="font-weight: bold; font-style: italic;">type</span>=<span style="font-style: italic;">"submit"</span> <span style="font-weight: bold; font-style: italic;">value</span>=<span style="font-style: italic;">"Upload"</span> /&gt;
                &lt;/<span style="font-weight: bold;">form</span>&gt;
        &lt;/<span style="font-weight: bold;">body</span>&gt;
&lt;/<span style="font-weight: bold;">html</span>&gt;
</pre>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-orgff47b02">
<h2 id="orgff47b02">Return Status Code 返回http状态码</h2>
<div class="outline-text-2" id="text-orgff47b02">
<p>
<a href="https://stackoverflow.com/questions/833715/returning-http-status-codes-in-python-cgi">https://stackoverflow.com/questions/833715/returning-http-status-codes-in-python-cgi</a>
</p>
<div class="org-src-container">
<pre class="src src-python" id="org5d75a85">
<span style="font-weight: bold;">print</span> <span style="font-style: italic;">"Status:301\nLocation: http://www.google.com"</span>
<span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">print("Status: 400")</span>
<span style="font-weight: bold; font-style: italic;"># </span><span style="font-weight: bold; font-style: italic;">print("Status: 401")</span>

</pre>
</div>
</div>
</div>
</div>
<div class="status" id="postamble">
<p class="author">Author: gdme1320</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
